home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / StencilBuffer / StencilMirror / StencilMirror.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  20.5 KB  |  565 lines

  1. //-----------------------------------------------------------------------------
  2. // File: StencilMirror.cpp
  3. //
  4. // Desc: Example code showing how to use stencil buffers to implement planar
  5. //       mirrors.
  6. //
  7. //       Note: This code uses the D3D Framework helper library.
  8. //
  9. // Copyright (c) 1998-2001 Microsoft Corporation. All rights reserved.
  10. //-----------------------------------------------------------------------------
  11. #define STRICT
  12. #include <math.h>
  13. #include <D3DX8.h>
  14. #include "D3DApp.h"
  15. #include "D3DFile.h"
  16. #include "D3DFont.h"
  17. #include "D3DUtil.h"
  18. #include "DXUtil.h"
  19.  
  20.  
  21.  
  22.  
  23. //-----------------------------------------------------------------------------
  24. // Custom vertex types
  25. //-----------------------------------------------------------------------------
  26. struct MESHVERTEX
  27. {
  28.     D3DXVECTOR3 p;
  29.     D3DXVECTOR3 n;
  30.     FLOAT       tu, tv;
  31. };
  32.  
  33. struct MIRRORVERTEX
  34. {
  35.     D3DXVECTOR3 p;
  36.     D3DXVECTOR3 n;
  37. };
  38.  
  39. #define D3DFVF_MESHVERTEX   (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
  40. #define D3DFVF_MIRRORVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)
  41.  
  42. #define FOG_COLOR 0x00000080
  43.  
  44. inline DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); }
  45.  
  46. inline FLOAT HeightField( FLOAT x, FLOAT z )
  47. {
  48.     FLOAT y = 0.0f;
  49.     y += 7.0f * cosf( 0.051f*x + 0.0f ) * sinf( 0.055f*x + 0.0f );
  50.     y += 7.0f * cosf( 0.053f*z + 0.0f ) * sinf( 0.057f*z + 0.0f );
  51.     y += 1.0f * cosf( 0.101f*x + 0.0f ) * sinf( 0.105f*x + 0.0f );
  52.     y += 1.0f * cosf( 0.103f*z + 0.0f ) * sinf( 0.107f*z + 0.0f );
  53.     y += 1.0f * cosf( 0.251f*x + 0.0f ) * sinf( 0.255f*x + 0.0f );
  54.     y += 1.0f * cosf( 0.253f*z + 0.0f ) * sinf( 0.257f*z + 0.0f );
  55.     return y;
  56. }
  57.  
  58.  
  59.  
  60.  
  61. //-----------------------------------------------------------------------------
  62. // Name: class CMyD3DApplication
  63. // Desc: Application class. The base class (CD3DApplication) provides the 
  64. //       generic functionality needed in all Direct3D samples. CMyD3DApplication 
  65. //       adds functionality specific to this sample program.
  66. //-----------------------------------------------------------------------------
  67. class CMyD3DApplication : public CD3DApplication
  68. {
  69.     CD3DFont* m_pFont;
  70.  
  71.     LPDIRECT3DVERTEXBUFFER8 m_pMirrorVB;
  72.     D3DMATERIAL8 m_mtrlMirrorMaterial;      // Material of the mirror
  73.     D3DXMATRIX   m_matMirrorMatrix;         // Matrix to position mirror
  74.  
  75.     CD3DFile*    m_pTerrain;                // X file of terrain
  76.     D3DXMATRIX   m_matTerrainMatrix;        // Matrix to position terrain
  77.  
  78.     CD3DFile*    m_pHelicopter;             // X file object to render
  79.     D3DXMATRIX   m_matHelicopterMatrix;     // Matrix to animate X file object
  80.  
  81.     HRESULT RenderScene();
  82.     HRESULT RenderMirror();
  83.     HRESULT CreateStencilBuffer();
  84.     HRESULT ConfirmDevice( D3DCAPS8*, DWORD, D3DFORMAT );
  85.  
  86. protected:
  87.     HRESULT OneTimeSceneInit();
  88.     HRESULT InitDeviceObjects();
  89.     HRESULT RestoreDeviceObjects();
  90.     HRESULT InvalidateDeviceObjects();
  91.     HRESULT DeleteDeviceObjects();
  92.     HRESULT Render();
  93.     HRESULT FrameMove();
  94.     HRESULT FinalCleanup();
  95.  
  96. public:
  97.     CMyD3DApplication();
  98. };
  99.  
  100.  
  101.  
  102.  
  103. //-----------------------------------------------------------------------------
  104. // Name: WinMain()
  105. // Desc: Entry point to the program. Initializes everything, and goes into a
  106. //       message-processing loop. Idle time is used to render the scene.
  107. //-----------------------------------------------------------------------------
  108. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  109. {
  110.     CMyD3DApplication d3dApp;
  111.  
  112.     if( FAILED( d3dApp.Create( hInst ) ) )
  113.         return 0;
  114.  
  115.     return d3dApp.Run();
  116. }
  117.  
  118.  
  119.  
  120.  
  121. //-----------------------------------------------------------------------------
  122. // Name: CMyD3DApplication()
  123. // Desc: Application constructor. Sets attributes for the app.
  124. //-----------------------------------------------------------------------------
  125. CMyD3DApplication::CMyD3DApplication()
  126. {
  127.     m_strWindowTitle    = _T("StencilMirror: Doing Reflections with Stencils");
  128.     m_bUseDepthBuffer   = TRUE;
  129.     m_dwMinDepthBits    = 16;
  130.     m_dwMinStencilBits  = 4;
  131.  
  132.     m_pFont             = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  133.     m_pTerrain          = new CD3DFile();
  134.     m_pHelicopter       = new CD3DFile();
  135.     m_pMirrorVB         = NULL;
  136. }
  137.  
  138.  
  139.  
  140.  
  141. //-----------------------------------------------------------------------------
  142. // Name: OneTimeSceneInit()
  143. // Desc: Called during initial app startup, this function performs all the
  144. //       permanent initialization.
  145. //-----------------------------------------------------------------------------
  146. HRESULT CMyD3DApplication::OneTimeSceneInit()
  147. {
  148.     return S_OK;
  149. }
  150.  
  151.  
  152.  
  153.  
  154. //-----------------------------------------------------------------------------
  155. // Name: FrameMove()
  156. // Desc: Called once per frame, the call is the entry point for animating
  157. //       the scene.
  158. //-----------------------------------------------------------------------------
  159. HRESULT CMyD3DApplication::FrameMove()
  160. {
  161.     // Position the terrain
  162.     D3DXMatrixTranslation( &m_matTerrainMatrix, 0.0f, 8.0f, 0.0f );
  163.  
  164.     // Position the mirror (water polygon intersecting with terrain)
  165.     D3DXMatrixTranslation( &m_matMirrorMatrix, 0.0f, 0.0f, 0.0f );
  166.  
  167.     // Position and animate the main object
  168.     FLOAT fObjectPosX = 50.0f*sinf(m_fTime/2);
  169.     FLOAT fObjectPosY = 6;
  170.     FLOAT fObjectPosZ = 10.0f*cosf(m_fTime/2);
  171.     D3DXMATRIX matRoll, matPitch, matRotate, matScale, matTranslate;
  172.     D3DXMatrixRotationZ( &matRoll, 0.2f*sinf(m_fTime/2)  );
  173.     D3DXMatrixRotationY( &matRotate, m_fTime/2-D3DX_PI/2  );
  174.     D3DXMatrixRotationX( &matPitch, -0.1f * (1+cosf(m_fTime))  );
  175.     D3DXMatrixScaling( &matScale, 0.5f, 0.5f, 0.5f );
  176.     D3DXMatrixTranslation( &matTranslate, fObjectPosX, fObjectPosY, fObjectPosZ );
  177.     D3DXMatrixMultiply( &m_matHelicopterMatrix, &matScale, &matTranslate );
  178.     D3DXMatrixMultiply( &m_matHelicopterMatrix, &matRoll, &m_matHelicopterMatrix );
  179.     D3DXMatrixMultiply( &m_matHelicopterMatrix, &matRotate, &m_matHelicopterMatrix );
  180.     D3DXMatrixMultiply( &m_matHelicopterMatrix, &matPitch, &m_matHelicopterMatrix );
  181.  
  182.     // Move the camera around
  183.     FLOAT fEyeX = 10.0f * sinf( m_fTime/2.0f );
  184.     FLOAT fEyeY =  3.0f * sinf( m_fTime/25.0f ) + 13.0f;
  185.     FLOAT fEyeZ =  5.0f * cosf( m_fTime/2.0f );
  186.     D3DXMATRIX matView;
  187.     D3DXVECTOR3 vEyePt    = D3DXVECTOR3( fEyeX, fEyeY, fEyeZ );
  188.     D3DXVECTOR3 vLookatPt = D3DXVECTOR3( fObjectPosX, fObjectPosY, fObjectPosZ );
  189.     D3DXVECTOR3 vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  190.     D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
  191.     m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  192.  
  193.     return S_OK;
  194. }
  195.  
  196.  
  197.  
  198.  
  199. //-----------------------------------------------------------------------------
  200. // Name: RenderScene()
  201. // Desc:
  202. //-----------------------------------------------------------------------------
  203. HRESULT CMyD3DApplication::RenderScene()
  204. {
  205.     // Render terrain
  206.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matTerrainMatrix );
  207.     m_pTerrain->Render( m_pd3dDevice );
  208.  
  209.     // Draw the mirror
  210.     m_pd3dDevice->SetTexture( 0, NULL );
  211.     m_pd3dDevice->SetMaterial( &m_mtrlMirrorMaterial );
  212.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matMirrorMatrix );
  213.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  214.     m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,     D3DBLEND_DESTCOLOR );
  215.     m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,    D3DBLEND_ZERO );
  216.     m_pd3dDevice->SetVertexShader( D3DFVF_MIRRORVERTEX );
  217.     m_pd3dDevice->SetStreamSource( 0, m_pMirrorVB, sizeof(MIRRORVERTEX) );
  218.     m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
  219.  
  220.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  221.  
  222.     // Draw the object. Note: do this last, in case the object has alpha
  223.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matHelicopterMatrix );
  224.     m_pHelicopter->Render( m_pd3dDevice );
  225.  
  226.     return S_OK;
  227. }
  228.  
  229.  
  230.  
  231.  
  232. //-----------------------------------------------------------------------------
  233. // Name: RenderMirror()
  234. // Desc:
  235. //-----------------------------------------------------------------------------
  236. HRESULT CMyD3DApplication::RenderMirror()
  237. {
  238.     // Turn depth buffer off, and stencil buffer on
  239.     m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE );
  240.     m_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC,     D3DCMP_ALWAYS );
  241.     m_pd3dDevice->SetRenderState( D3DRS_STENCILREF,      0x1 );
  242.     m_pd3dDevice->SetRenderState( D3DRS_STENCILMASK,     0xffffffff );
  243.     m_pd3dDevice->SetRenderState( D3DRS_STENCILWRITEMASK,0xffffffff );
  244.     m_pd3dDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
  245.     m_pd3dDevice->SetRenderState( D3DRS_STENCILFAIL,  D3DSTENCILOP_KEEP );
  246.     m_pd3dDevice->SetRenderState( D3DRS_STENCILPASS,  D3DSTENCILOP_REPLACE );
  247.  
  248.     // Make sure no pixels are written to the z-buffer or frame buffer
  249.     m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE,  FALSE );
  250.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  251.     m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_ZERO );
  252.     m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
  253.  
  254.     // Draw the reflecting surface into the stencil buffer
  255.     m_pd3dDevice->SetTexture( 0, NULL);
  256.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matMirrorMatrix );
  257.     m_pd3dDevice->SetVertexShader( D3DFVF_MIRRORVERTEX );
  258.     m_pd3dDevice->SetStreamSource( 0, m_pMirrorVB, sizeof(MIRRORVERTEX) );
  259.     m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
  260.  
  261.     // Save the view matrix
  262.     D3DXMATRIX matViewSaved;
  263.     m_pd3dDevice->GetTransform( D3DTS_VIEW, &matViewSaved );
  264.  
  265.     // Reflect camera in X-Z plane mirror
  266.     D3DXMATRIX matView, matReflect;
  267.     D3DXPLANE plane;
  268.     D3DXPlaneFromPointNormal( &plane, &D3DXVECTOR3(0,0,0), &D3DXVECTOR3(0,1,0) );
  269.     D3DXMatrixReflect( &matReflect, &plane );
  270.     D3DXMatrixMultiply( &matView, &matReflect, &matViewSaved );
  271.     m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  272.  
  273.     // Set a clip plane, so that only objects above the water are reflected
  274.     m_pd3dDevice->SetClipPlane( 0, plane );
  275.     m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 0x01 );
  276.  
  277.     // Setup render states to a blended render scene against mask in stencil
  278.     // buffer. An important step here is to reverse the cull-order of the
  279.     // polygons, since the view matrix is being relected.
  280.     m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
  281.     m_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC,  D3DCMP_EQUAL );
  282.     m_pd3dDevice->SetRenderState( D3DRS_STENCILPASS,  D3DSTENCILOP_KEEP );
  283.     m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,     D3DBLEND_DESTCOLOR );
  284.     m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,    D3DBLEND_ZERO );
  285.     m_pd3dDevice->SetRenderState( D3DRS_CULLMODE,     D3DCULL_CW );
  286.  
  287.     // Clear the zbuffer (leave frame- and stencil-buffer intact)
  288.     m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER, 0L, 1.0f, 0L );
  289.  
  290.     // Render the scene
  291.     RenderScene();
  292.  
  293.     // Restore render states
  294.     m_pd3dDevice->SetRenderState( D3DRS_CULLMODE,         D3DCULL_CCW );
  295.     m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE,    FALSE );
  296.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  297.     m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE,  0x00 );
  298.     m_pd3dDevice->SetTransform( D3DTS_VIEW, &matViewSaved );
  299.  
  300.     return S_OK;
  301. }
  302.  
  303.  
  304.  
  305.  
  306. //-----------------------------------------------------------------------------
  307. // Name: Render()
  308. // Desc: Called once per frame, the call is the entry point for 3d
  309. //       rendering. This function sets up render states, clears the
  310. //       viewport, and renders the scene.
  311. //-----------------------------------------------------------------------------
  312. HRESULT CMyD3DApplication::Render()
  313. {
  314.     // Clear the viewport, zbuffer, and stencil buffer
  315.     m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
  316.                          FOG_COLOR, 1.0f, 0L );
  317.  
  318.     // Begin the scene
  319.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  320.     {
  321.         // Render the scene
  322.         RenderScene();
  323.  
  324.         // Render the reflection in the mirror
  325.         RenderMirror();
  326.  
  327.         // Output statistics
  328.         m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  329.         m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  330.  
  331.         // End the scene.
  332.         m_pd3dDevice->EndScene();
  333.      }
  334.  
  335.     return S_OK;
  336. }
  337.  
  338.  
  339.  
  340.  
  341. //-----------------------------------------------------------------------------
  342. // Name: InitDeviceObjects()
  343. // Desc: Initialize scene objects.
  344. //-----------------------------------------------------------------------------
  345. HRESULT CMyD3DApplication::InitDeviceObjects()
  346. {
  347.     // Initialize the font's internal textures
  348.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  349.  
  350.     // Load the main file object
  351.     if( FAILED( m_pHelicopter->Create( m_pd3dDevice, _T("Heli.x") ) ) )
  352.         return D3DAPPERR_MEDIANOTFOUND;
  353.  
  354.     // Load the terrain
  355.     if( FAILED( m_pTerrain->Create( m_pd3dDevice, _T("SeaFloor.x") ) ) )
  356.         return D3DAPPERR_MEDIANOTFOUND;
  357.  
  358.     // Tweak the terrain vertices to add some bumpy terrain
  359.     CD3DMesh* pMesh = m_pTerrain->FindMesh( _T("SeaFloor") );
  360.     if( pMesh )
  361.     {
  362.         // Set FVF to VertexFVF
  363.         pMesh->SetFVF( m_pd3dDevice, D3DFVF_MESHVERTEX );
  364.  
  365.         // Get access to the mesh vertices
  366.         LPDIRECT3DVERTEXBUFFER8 pVB;
  367.         MESHVERTEX* pVertices;
  368.         DWORD dwNumVertices = pMesh->GetSysMemMesh()->GetNumVertices();
  369.         pMesh->GetSysMemMesh()->GetVertexBuffer( &pVB );
  370.         pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 );
  371.  
  372.         for( DWORD i=0; i<dwNumVertices; i++ )
  373.         {
  374.             D3DXVECTOR3 v00( pVertices[i].p.x + 0.0f, 0.0f, pVertices[i].p.z + 0.0f );
  375.             D3DXVECTOR3 v10( pVertices[i].p.x + 0.1f, 0.0f, pVertices[i].p.z + 0.0f );
  376.             D3DXVECTOR3 v01( pVertices[i].p.x + 0.0f, 0.0f, pVertices[i].p.z + 0.1f );
  377.             v00.y = HeightField( 1*v00.x, 1*v00.z );
  378.             v10.y = HeightField( 1*v10.x, 1*v10.z );
  379.             v01.y = HeightField( 1*v01.x, 1*v01.z );
  380.  
  381.             D3DXVECTOR3 n;
  382.             D3DXVec3Cross( &n, &(v01-v00), &(v10-v00) );
  383.             D3DXVec3Normalize( &n, &n );
  384.  
  385.             pVertices[i].p.y  = v00.y;
  386.             pVertices[i].n.x  = n.x;
  387.             pVertices[i].n.y  = n.y;
  388.             pVertices[i].n.z  = n.z;
  389.             pVertices[i].tu  *= 10;
  390.             pVertices[i].tv  *= 10;
  391.         }
  392.  
  393.         pVB->Unlock();
  394.         pVB->Release();
  395.     }
  396.  
  397.     // Create a big square for rendering the mirror
  398.     if( FAILED( m_pd3dDevice->CreateVertexBuffer( 4*sizeof(MIRRORVERTEX),
  399.                                        D3DUSAGE_WRITEONLY, D3DFVF_MIRRORVERTEX,
  400.                                        D3DPOOL_MANAGED, &m_pMirrorVB ) ) )
  401.         return E_FAIL;
  402.  
  403.     MIRRORVERTEX* v;
  404.     m_pMirrorVB->Lock( 0, 0, (BYTE**)&v, 0 );
  405.     v[0].p = D3DXVECTOR3(-80.0f, 0.0f,-80.0f );
  406.     v[0].n = D3DXVECTOR3( 0.0f,  1.0f,  0.0f );
  407.     v[1].p = D3DXVECTOR3(-80.0f, 0.0f, 80.0f );
  408.     v[1].n = D3DXVECTOR3( 0.0f,  1.0f,  0.0f );
  409.     v[2].p = D3DXVECTOR3( 80.0f, 0.0f,-80.0f );
  410.     v[2].n = D3DXVECTOR3( 0.0f,  1.0f,  0.0f );
  411.     v[3].p = D3DXVECTOR3( 80.0f, 0.0f, 80.0f );
  412.     v[3].n = D3DXVECTOR3( 0.0f,  1.0f,  0.0f );
  413.     m_pMirrorVB->Unlock();
  414.  
  415.     return S_OK;
  416. }
  417.  
  418.  
  419.  
  420.  
  421. //-----------------------------------------------------------------------------
  422. // Name: RestoreDeviceObjects()
  423. // Desc: Restore device-memory objects and state after a device is created or
  424. //       resized.
  425. //-----------------------------------------------------------------------------
  426. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  427. {
  428.     m_pFont->RestoreDeviceObjects();
  429.  
  430.     // Build the device objects for the file-based objecs
  431.     m_pHelicopter->RestoreDeviceObjects( m_pd3dDevice );
  432.     m_pTerrain->RestoreDeviceObjects( m_pd3dDevice );
  433.  
  434.     // Set up textures
  435.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  436.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  437.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  438.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  439.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  440.  
  441.     // Set up misc render states
  442.     m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,        TRUE );
  443.     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE,   TRUE );
  444.     m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
  445.     m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,        0x00555555 );
  446.  
  447.     // Set the transform matrices
  448.     D3DXVECTOR3 vEyePt    = D3DXVECTOR3( 0.0f, 5.5f, -15.0f );
  449.     D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 1.5f,   0.0f  );
  450.     D3DXVECTOR3 vUpVec    = D3DXVECTOR3( 0.0f, 1.0f,   0.0f  );
  451.     D3DXMATRIX matWorld, matView, matProj;
  452.  
  453.     D3DXMatrixIdentity( &matWorld );
  454.     D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
  455.     FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
  456.     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 1000.0f );
  457.  
  458.     m_pd3dDevice->SetTransform( D3DTS_WORLD,      &matWorld );
  459.     m_pd3dDevice->SetTransform( D3DTS_VIEW,       &matView );
  460.     m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  461.  
  462.     // Set up a material
  463.     D3DUtil_InitMaterial( m_mtrlMirrorMaterial, 0.5f, 0.8f, 1.0f );
  464.  
  465.     // Set up the light
  466.     D3DLIGHT8 light;
  467.     D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.0f, -1.0f, 1.0f );
  468.     m_pd3dDevice->SetLight( 0, &light );
  469.     m_pd3dDevice->LightEnable( 0, TRUE );
  470.  
  471.     // Turn on fog
  472.     FLOAT fFogStart =  80.0f;
  473.     FLOAT fFogEnd   = 100.0f;
  474.     m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,      TRUE );
  475.     m_pd3dDevice->SetRenderState( D3DRS_FOGCOLOR,       FOG_COLOR );
  476.     m_pd3dDevice->SetRenderState( D3DRS_FOGTABLEMODE,   D3DFOG_NONE );
  477.     m_pd3dDevice->SetRenderState( D3DRS_FOGVERTEXMODE,  D3DFOG_LINEAR );
  478.     m_pd3dDevice->SetRenderState( D3DRS_RANGEFOGENABLE, FALSE );
  479.     m_pd3dDevice->SetRenderState( D3DRS_FOGSTART,       FtoDW(fFogStart) );
  480.     m_pd3dDevice->SetRenderState( D3DRS_FOGEND,         FtoDW(fFogEnd) );
  481.  
  482.     return S_OK;
  483. }
  484.  
  485.  
  486.  
  487.  
  488. //-----------------------------------------------------------------------------
  489. // Name: InvalidateDeviceObjects()
  490. // Desc: Called when the device-dependent objects are about to be lost.
  491. //-----------------------------------------------------------------------------
  492. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  493. {
  494.     m_pFont->InvalidateDeviceObjects();
  495.     m_pTerrain->InvalidateDeviceObjects();
  496.     m_pHelicopter->InvalidateDeviceObjects();
  497.  
  498.     return S_OK;
  499. }
  500.  
  501.  
  502.  
  503.  
  504. //-----------------------------------------------------------------------------
  505. // Name: DeleteDeviceObjects()
  506. // Desc: Called when the app is exiting, or the device is being changed,
  507. //       this function deletes any device dependent objects.
  508. //-----------------------------------------------------------------------------
  509. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  510. {
  511.     m_pFont->DeleteDeviceObjects();
  512.     m_pTerrain->Destroy();
  513.     m_pHelicopter->Destroy();
  514.  
  515.     SAFE_RELEASE( m_pMirrorVB );
  516.  
  517.     return S_OK;
  518. }
  519.  
  520.  
  521.  
  522.  
  523. //-----------------------------------------------------------------------------
  524. // Name: FinalCleanup()
  525. // Desc: Called before the app exits, this function gives the app the chance
  526. //       to cleanup after itself.
  527. //-----------------------------------------------------------------------------
  528. HRESULT CMyD3DApplication::FinalCleanup()
  529. {
  530.     SAFE_DELETE( m_pFont );
  531.     SAFE_DELETE( m_pTerrain );
  532.     SAFE_DELETE( m_pHelicopter );
  533.  
  534.     return S_OK;
  535. }
  536.  
  537.  
  538.  
  539.  
  540. //-----------------------------------------------------------------------------
  541. // Name: ConfirmDevice()
  542. // Desc: Called during device intialization, this code checks the device
  543. //       for some minimum set of capabilities
  544. //-----------------------------------------------------------------------------
  545. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  546.                                           D3DFORMAT Format )
  547. {
  548.     if( dwBehavior & D3DCREATE_PUREDEVICE )
  549.         return E_FAIL; // GetTransform doesn't work on PUREDEVICE
  550.  
  551.     // Make sure device supports directional lights
  552.     if( (dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING ) ||
  553.         (dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING ) )
  554.     {
  555.         if( 0 == ( pCaps->VertexProcessingCaps & D3DVTXPCAPS_DIRECTIONALLIGHTS ) )
  556.             return E_FAIL;
  557.     }
  558.  
  559.     return S_OK;
  560. }
  561.  
  562.  
  563.  
  564.  
  565.